package com.bidevalution.support.util;

import com.qtp.core.util.Base64Util;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import java.io.IOException;
import java.security.SecureRandom;

/**
 * @author huyiqi
 * @date 2019/11/11
 */
public class DesUtil {
    private final static String DES = "DES";

    /**
     * Description 根据键值进行加密
     * @param data 要加密的字符串数据
     * @param key  加密键byte数组
     * @return 返回加密后的字符串数据
     * @throws Exception 抛出异常
     */
    public static String encrypt(String data, String key) throws Exception {
        return encrypt(data, key, null);
    }

    public static String encrypt(String data, String key, byte[] iv) throws Exception {
        if(StringUtils.isBlank(data) || StringUtils.isBlank(key)) {
            return null;
        }
        byte[] bt = encrypt(data.getBytes(), key.getBytes(), iv);
        return Base64Util.encryptBase64(bt);
    }

    /**
     * Description 根据键值进行解密
     * @param data 需要解密的字符串数据
     * @param key  加密键byte数组
     * @return 返回解密后的数据
     * @throws IOException 抛出IO异常
     * @throws Exception 抛出lang异常
     */
    public static String decrypt(String data, String key) throws IOException, Exception {
        return decrypt(data, key, null);
    }

    public static String decrypt(String data, String key, byte[] iv) throws IOException, Exception {
        if(StringUtils.isBlank(data) || StringUtils.isBlank(key)) {
            return "";
        }
        byte[] buf = Base64Util.decryptBase64(data);
        byte[] bt = decrypt(buf,key.getBytes(), iv);
        return new String(bt);
    }

    /**
     * Description 根据键值进行加密
     * @param data 需要加密byte数组
     * @param key  加密键byte数组
     * @return 返回加密后的byte数组
     * @throws Exception 抛出lang异常
     */
    private static byte[] encrypt(byte[] data, byte[] key, byte[] ivParam) throws Exception {

        Cipher cipher = initCipher(key, ivParam, Cipher.ENCRYPT_MODE);

        return cipher.doFinal(data);
    }
    /**
     * Description 根据键值进行解密
     * @param data 需要解密的byte数组
     * @param key  加密键byte数组
     * @return 返回解密后的byte数组
     * @throws Exception 抛出lang异常
     */
    private static byte[] decrypt(byte[] data, byte[] key, byte[] ivParam) throws Exception {
        Cipher cipher = initCipher(key, ivParam, Cipher.DECRYPT_MODE);

        return cipher.doFinal(data);
    }

    /**
     * 初始化操作对象
     * @param key 密钥
     * @param ivParam 偏移量
     * @param mode 模式
     * @return 返回操作对象
     * @throws Exception
     */
    private static Cipher initCipher(byte[] key, byte[] ivParam, int mode) throws Exception {
        // 从原始密钥数据创建DESKeySpec对象
        DESKeySpec dks = new DESKeySpec(key);

        // 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
        SecretKey securekey = keyFactory.generateSecret(dks);

        // Cipher对象实际完成加密操作
        Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

        // 初始化cipher
        if(ivParam != null) {
            //偏移量
            IvParameterSpec iv = new IvParameterSpec(ivParam);
            cipher.init(mode, securekey, iv);
        } else {
            // 生成一个可信任的随机数源
            SecureRandom sr = new SecureRandom();
            cipher.init(mode, securekey, sr);
        }

        return cipher;
    }
}
